package com.bcbim.operation_maintenance.space_inventory_report.service;

import com.bcbim.common.sys.Code;
import com.bcbim.common.util.ExcelUtil;
import com.bcbim.common.util.GuidUtil;
import com.bcbim.operation_maintenance.space_inventory_report.mapper.SpaceInventoryReportMapper;
import com.bcbim.operation_maintenance.space_inventory_report_query.mapper.SpaceInventoryReportQueryMapper;
import com.bcbim.operation_maintenance.space_inventory_report_table_head.mapper.SpaceInventoryReportTableHeadMapper;
import com.bcbim.operation_maintenance_interface.space_inventory_report.dao.SpaceInventoryReportDAO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.dto.ListSpaceInventoryReportDTO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.dto.ReportTableHeadDTO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.dto.SpaceInventoryReportDTO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.service.SpaceInventoryReportService;
import com.bcbim.operation_maintenance_interface.space_inventory_report.vo.ListSpaceInventoryReportNameVO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.vo.ListSpaceInventoryReportVO;
import com.bcbim.operation_maintenance_interface.space_inventory_report.vo.TotalSpaceInventoryReportVO;
import com.bcbim.operation_maintenance_interface.space_inventory_report_query.dao.SpaceInventoryReportQueryDAO;
import com.bcbim.operation_maintenance_interface.space_inventory_report_table_head.dao.SpaceInventoryReportTableHeadDAO;
import com.bcbim.operation_maintenance_interface.space_inventory_report_table_head.vo.SpaceInventoryReportTableHeadVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @version V 1.0.0
 * @Description：空间清册报表service实现类
 * @Author: haomeijie
 * @Date: 2022/4/13 13:50
 **/
@Service(timeout = 60 * 1000, group = "spaceInventoryReport", version = "1.0.0")
public class SpaceInventoryReportServiceImpl implements SpaceInventoryReportService {
    @Autowired
    private SpaceInventoryReportMapper spaceInventoryReportMapper;
    @Autowired
    private SpaceInventoryReportQueryMapper spaceInventoryReportQueryMapper;
    @Autowired
    private SpaceInventoryReportTableHeadMapper spaceInventoryReportTableHeadMapper;

    @Override
    public int listSpaceInventoryReportCount(ListSpaceInventoryReportDTO listSpaceInventoryReportDTO) {
        return spaceInventoryReportMapper.listSpaceInventoryReportCount(listSpaceInventoryReportDTO);
    }

    @Override
    public List<ListSpaceInventoryReportVO> listSpaceInventoryReport(ListSpaceInventoryReportDTO listSpaceInventoryReportDTO) {
        List<ListSpaceInventoryReportVO> list = spaceInventoryReportMapper.listSpaceInventoryReport(listSpaceInventoryReportDTO);

        //保留两位小数
        DecimalFormat df = new DecimalFormat("#0.00");

        //计算总面积
        Double spaceSum = spaceInventoryReportMapper.getSpaceSum(listSpaceInventoryReportDTO);
        for (ListSpaceInventoryReportVO spaceInventoryReportVO : list) {
            //计算面积占比：单个空间面积/查询出的总面积
            if (spaceInventoryReportVO.getSpaceArea() == 0) {
                spaceInventoryReportVO.setAreaProportion(String.valueOf(0));
            } else {
                String areaProportion = df.format(spaceInventoryReportVO.getSpaceArea() / spaceSum * 100);
                spaceInventoryReportVO.setAreaProportion(areaProportion + "%");
            }
            //占用率 公式=实际人数/额定人数
            //1、空白: ①该空间可占用，额定人数为空或额定人数为0；②该空间不可占用
            if (StringUtils.isNotEmpty(spaceInventoryReportVO.getOccupy()) && ((spaceInventoryReportVO.getOccupy().equals("是")
                    && (ObjectUtils.isEmpty(spaceInventoryReportVO.getFixPeopleNum()) || spaceInventoryReportVO.getFixPeopleNum() == 0))
                    || spaceInventoryReportVO.getOccupy().equals("否"))) {
                spaceInventoryReportVO.setOccupyRate(null);
            }
            //2、0: 可占用，实际人数为0，额定人数>0
            if (StringUtils.isNotEmpty(spaceInventoryReportVO.getOccupy()) && spaceInventoryReportVO.getOccupy().equals("是")
                    && spaceInventoryReportVO.getFixPeopleNum() > 0 && spaceInventoryReportVO.getActualPeopleNum() == 0) {
                spaceInventoryReportVO.setOccupyRate(String.valueOf(0));
            }
            //3、正常计算:(可以大于100%，实际>额定) 该空间可占用，且有额定和实际人数值
            if (StringUtils.isNotEmpty(spaceInventoryReportVO.getOccupy()) && spaceInventoryReportVO.getOccupy().equals("是")
                    && spaceInventoryReportVO.getFixPeopleNum() > 0 && spaceInventoryReportVO.getActualPeopleNum() > 0) {
                String occupyRate = df.format((float) spaceInventoryReportVO.getActualPeopleNum() / spaceInventoryReportVO.getFixPeopleNum() * 100);
                spaceInventoryReportVO.setOccupyRate(occupyRate + "%");
            }
            //人员平均面积：空间面积/实际人数
            //空白：实际人数为0
            if (ObjectUtils.isEmpty(spaceInventoryReportVO.getActualPeopleNum()) || spaceInventoryReportVO.getActualPeopleNum() == 0) {
                spaceInventoryReportVO.setAverageArea(String.valueOf(0));
            }
            //正常计算：有实际人数
            if (spaceInventoryReportVO.getActualPeopleNum() > 0) {
                String averageArea = df.format(spaceInventoryReportVO.getSpaceArea() / spaceInventoryReportVO.getActualPeopleNum());
                spaceInventoryReportVO.setAverageArea(averageArea);
            }
        }
        return list;
    }

    @Override
    public String exportSpaceInventoryReport(List<ListSpaceInventoryReportVO> list, List<ReportTableHeadDTO> headList, String uploadPath) {
        //整理表头内容，生成导出模板
        String filename = "spaceInventoryReport.xls";
        String[] title = new String[headList.size()];
        String[][] content = new String[1][title.length];
        for (int i = 0; i < headList.size(); i++) {
            title[i] = headList.get(i).getLabel();
            content[0][i] = String.valueOf("${list." + headList.get(i).getProp() + "}");
        }
        //创建模板文件
        checkedFolder(uploadPath + "template");
        File templateFile = new File(uploadPath + "template" + File.separator + filename);
        //生成导出模板
        GenerateTemplate(title, content, templateFile);
        //创建导出文件
        checkedFolder(uploadPath + "export");
        String filepath = "export" + File.separator + "空间清册报表.xls";
        File file = new File(uploadPath + filepath);
        //查询列表数据
        Map<String, Object> param = new HashMap<>();
        param.put("list", list);
        try {
            //进行数据导出
            ExcelUtil.downLoadExcel(templateFile, file, param);
            return filepath;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //判断文件夹是否存在
    public void checkedFolder(String fold) {
        File folder = new File(fold);
        if (!folder.exists()) {
            folder.mkdirs();
        }
    }

    /**
     * 在本地生成导出文件模板
     *
     * @Author: haomeijie
     * @Date: 2022/3/18 14:03
     */
    public void GenerateTemplate(String[] title, String[][] content, File file) {
        String sheetName = "Sheet1";

        HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName, title, content, null);
        try {
            FileOutputStream output = new FileOutputStream(file);
            wb.write(output);//写入磁盘
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param spaceInventoryReportDTO
     * @Description: 空间清册报表名称列表
     * @Date: 2022/4/14 10:51
     * @Param: [spaceInventoryReportDTO]
     * @return: java.util.List<com.bcbim.model_interface.space_inventory_report.vo.ListSpaceInventoryReportNameVO>
     * @Author: lihonggang
     */
    @Override
    public List<ListSpaceInventoryReportNameVO> listSpaceInventoryReportName(SpaceInventoryReportDTO spaceInventoryReportDTO) {
        return spaceInventoryReportMapper.listSpaceInventoryReportName(spaceInventoryReportDTO);
    }

    /**
     * @param spaceInventoryReportDTO
     * @Description: 查询空间清册报表名称列表总数
     * @Date: 2022/4/14 11:07
     * @Param: [spaceInventoryReportDTO]
     * @return: int
     * @Author: lihonggang
     */
    @Override
    public int countListSpaceInventoryReportName(SpaceInventoryReportDTO spaceInventoryReportDTO) {
        return spaceInventoryReportMapper.countListSpaceInventoryReportName(spaceInventoryReportDTO);
    }

    /**
     * @param spaceInventoryReportDAO
     * @Description: 修改空间清册报表名称
     * @Date: 2022/4/14 14:32
     * @Param: [spaceInventoryReportDAO]
     * @return: int
     * @Author: lihonggang
     */
    @Override
    public int updateSpaceInventoryReportName(SpaceInventoryReportDAO spaceInventoryReportDAO) {
        return spaceInventoryReportMapper.updateSpaceInventoryReportName(spaceInventoryReportDAO);
    }

    @Override
    public boolean checkReportName(SpaceInventoryReportDAO spaceInventoryReportDAO) {
        return spaceInventoryReportMapper.checkReportName(spaceInventoryReportDAO) > 0 ? true : false;
    }

    @Override
    public int updateSpaceInventoryReport(SpaceInventoryReportDAO spaceInventoryReportDAO, ListSpaceInventoryReportDTO reportDTO, List<SpaceInventoryReportTableHeadDAO> headList) {
        //整理表头参数
        headList.stream().forEach(head -> {
            head.setId(GuidUtil.get());
            head.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
        });
        //添加表头参数到数据库
        int i = spaceInventoryReportTableHeadMapper.batchUpdate(headList);
        //整理筛选条件参数
        List<SpaceInventoryReportQueryDAO> queryList = new ArrayList<>();
        Field[] fields = reportDTO.getClass().getDeclaredFields();
        for (int j = 3; j < fields.length; j++) {
            fields[j].setAccessible(true);
            if (fields[j].getName().equals("spaceTypeIds") || fields[j].getName().equals("departmentIds")) {
                continue;
            }
            //整理筛选条件参数
            SpaceInventoryReportQueryDAO queryDAO = new SpaceInventoryReportQueryDAO();
            queryDAO.setId(GuidUtil.get());
            queryDAO.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
            queryDAO.setQueryProp(fields[j].getName());
            try {
                String queryValue = String.valueOf(fields[j].get(reportDTO));
                if (StringUtils.isEmpty(queryValue) || queryValue.equals("null")) {
                    queryValue = null;
                }
                if (fields[j].getName().equals("floorIds") && StringUtils.isNotEmpty(queryValue)) {
                    queryValue = queryValue.substring(1, queryValue.length() - 1);
                }
                if (fields[j].getName().equals("topCategory") && StringUtils.isNotEmpty(queryValue)) {
                    queryValue = queryValue.substring(1, queryValue.length() - 1);
                }
                queryDAO.setQueryValue(queryValue);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            queryDAO.setCreateTime(LocalDateTime.now());
            queryList.add(queryDAO);
        }
        spaceInventoryReportQueryMapper.batchUpdate(queryList);
        return i;
    }

    @Override
    @Transactional
    public int insertSpaceInventoryReport(SpaceInventoryReportDAO spaceInventoryReportDAO, ListSpaceInventoryReportDTO reportDTO, List<SpaceInventoryReportTableHeadDAO> headList) {
        //新增空间清册报表
        int i = spaceInventoryReportMapper.insertSpaceInventoryReport(spaceInventoryReportDAO);
        //整理表头参数
        headList.stream().forEach(head -> {
            head.setId(GuidUtil.get());
            head.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
            head.setCreateTime(LocalDateTime.now());
        });
        //添加表头参数到数据库
        spaceInventoryReportTableHeadMapper.batchInsert(headList);
        //整理筛选条件参数
        List<SpaceInventoryReportQueryDAO> queryList = new ArrayList<>();
        Field[] fields = reportDTO.getClass().getDeclaredFields();
        for (int j = 3; j < fields.length; j++) {
            fields[j].setAccessible(true);
            if (fields[j].getName().equals("spaceTypeIds") || fields[j].getName().equals("departmentIds")) {
                continue;
            }
            //整理筛选条件参数
            SpaceInventoryReportQueryDAO queryDAO = new SpaceInventoryReportQueryDAO();
            queryDAO.setId(GuidUtil.get());
            queryDAO.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
            queryDAO.setQueryProp(fields[j].getName());
            try {
                String queryValue = String.valueOf(fields[j].get(reportDTO));
                if (StringUtils.isEmpty(queryValue) || queryValue.equals("null")) {
                    queryValue = null;
                }
                if (fields[j].getName().equals("floorIds") && StringUtils.isNotEmpty(queryValue)) {
                    queryValue = queryValue.substring(1, queryValue.length() - 1);
                }
                if (fields[j].getName().equals("topCategory") && StringUtils.isNotEmpty(queryValue)) {
                    queryValue = queryValue.substring(1, queryValue.length() - 1);
                }
                queryDAO.setQueryValue(queryValue);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            queryDAO.setCreateTime(LocalDateTime.now());
            queryList.add(queryDAO);
        }
        spaceInventoryReportQueryMapper.batchInsert(queryList);
        return i;
    }

    @Override
    public List<Code> listQuery(String spaceInventoryReportId) {
        return spaceInventoryReportQueryMapper.listQuery(spaceInventoryReportId);
    }

    @Override
    public List<String> listReportName(String reportName, String projectId) {
        return spaceInventoryReportMapper.listReportName(reportName, projectId);
    }

    @Override
    public int copySpaceInventoryReport(SpaceInventoryReportDAO spaceInventoryReportDAO, List<Code> query, List<SpaceInventoryReportTableHeadVO> head) {
        //新增空间清册报表
        int i = spaceInventoryReportMapper.insertSpaceInventoryReport(spaceInventoryReportDAO);
        //整理表头参数
        List<SpaceInventoryReportTableHeadDAO> headList = new ArrayList<>();
        head.stream().forEach(headVO -> {
            SpaceInventoryReportTableHeadDAO headDAO = new SpaceInventoryReportTableHeadDAO();
            BeanUtils.copyProperties(headVO, headDAO);
            headDAO.setId(GuidUtil.get());
            headDAO.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
            headDAO.setCreateTime(LocalDateTime.now());
            headList.add(headDAO);
        });
        //添加表头参数到数据库
        spaceInventoryReportTableHeadMapper.batchInsert(headList);
        //整理筛选条件参数
        List<SpaceInventoryReportQueryDAO> queryList = new ArrayList<>();
        query.stream().forEach(code -> {
            SpaceInventoryReportQueryDAO queryDAO = new SpaceInventoryReportQueryDAO();
            queryDAO.setId(GuidUtil.get());
            queryDAO.setSpaceInventoryReportId(spaceInventoryReportDAO.getId());
            queryDAO.setQueryProp(code.getCode());
            queryDAO.setQueryValue(code.getValue());
            queryDAO.setCreateTime(LocalDateTime.now());
            queryList.add(queryDAO);
        });
        spaceInventoryReportQueryMapper.batchInsert(queryList);
        return i;

    }

    @Override
    public TotalSpaceInventoryReportVO getTotal(ListSpaceInventoryReportDTO listSpaceInventoryReportDTO) {
        List<ListSpaceInventoryReportVO> list = spaceInventoryReportMapper.listSpaceInventoryReport(listSpaceInventoryReportDTO);
        Integer spaceCount = spaceInventoryReportMapper.listSpaceInventoryReportCount(listSpaceInventoryReportDTO);//空间数
        Integer fixPeoPle = 0;//额定人数
        Integer actualPeoPle = 0;//实际人数
        Double occupyRate = 0.00;//占用率
        Double averageArea = 0.00;//人员平均面积
        //保留两位小数
        DecimalFormat df = new DecimalFormat("#0.00");

        //计算总面积
        Double spaceArea = spaceInventoryReportMapper.getSpaceSum(listSpaceInventoryReportDTO);
        for (ListSpaceInventoryReportVO spaceInventoryReportVO : list) {
            //总计额定人数
            fixPeoPle += spaceInventoryReportVO.getFixPeopleNum();
            //总计实际人数
            actualPeoPle += spaceInventoryReportVO.getActualPeopleNum();
            //总计占用率
            //2、0: 可占用，实际人数为0，额定人数>0
            if (StringUtils.isNotEmpty(spaceInventoryReportVO.getOccupy()) && spaceInventoryReportVO.getOccupy().equals("是")
                    && spaceInventoryReportVO.getFixPeopleNum() > 0 && spaceInventoryReportVO.getActualPeopleNum() == 0) {
                occupyRate += 0.00;
            }
            //3、正常计算:(可以大于100%，实际>额定) 该空间可占用，且有额定和实际人数值
            if (StringUtils.isNotEmpty(spaceInventoryReportVO.getOccupy()) && spaceInventoryReportVO.getOccupy().equals("是")
                    && spaceInventoryReportVO.getFixPeopleNum() > 0 && spaceInventoryReportVO.getActualPeopleNum() > 0) {
                occupyRate += spaceInventoryReportVO.getActualPeopleNum() / spaceInventoryReportVO.getFixPeopleNum() * 100;
            }
            //人员平均面积：空间面积/实际人数
            //空白：实际人数为0
            if (ObjectUtils.isEmpty(spaceInventoryReportVO.getActualPeopleNum()) || spaceInventoryReportVO.getActualPeopleNum() == 0) {
                averageArea += 0.00;
            }
            //正常计算：有实际人数
            if (spaceInventoryReportVO.getActualPeopleNum() > 0) {
                averageArea += spaceInventoryReportVO.getSpaceArea() / spaceInventoryReportVO.getActualPeopleNum();
            }
        }
        TotalSpaceInventoryReportVO total = new TotalSpaceInventoryReportVO();
        total.setSpaceCount(spaceCount);
        total.setSpaceArea(spaceArea);
        total.setFixPeoPle(fixPeoPle);
        total.setActualPeoPle(actualPeoPle);
        total.setOccupyRate(df.format(occupyRate) + "%");
        total.setAverageArea(df.format(averageArea));
        if (ObjectUtils.isEmpty(spaceArea) || spaceArea == 0) {

            total.setAreaProportion(String.valueOf(0));
        } else {
            total.setAreaProportion(String.valueOf(spaceArea / spaceArea * 100) + "%");
        }
        return total;
    }


}
